package com.sczmgk.frame.http;


import com.sczmgk.hotline.utils.MyLog;

import java.lang.Thread.State;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

public class HttpConnector {
	private static final String TAG = HttpConnector.class.getSimpleName();

	private static final int MAX_THREAD_ACTION = 3;

	private static final int MAX_THREAD_DOWN = 3;
	private static final int MAX_THREAD_UPLOAD = 3;
	private static HttpConnector instance;

	private static Object object = new Object();

	private Vector<HttpRequest> mRequestQueue;
	private Vector<HttpRequest> mRequestQueueCurr;

	private ArrayList<HttpThread> mThreadList;
	
	private HttpSimpleListener mFilterListener;
	private HttpConnector(HttpSimpleListener listener) {
		super();

		mRequestQueue = new Vector<HttpRequest>();
		mRequestQueueCurr = new Vector<HttpRequest>();
		mThreadList = new ArrayList<HttpThread>();
		mFilterListener = listener;
	}
	
	public static HttpSimpleListener getHttpFilterListener(){
		if (instance != null) {
			return instance.mFilterListener;
		}
		return null;
	}

	public static void init(HttpSimpleListener listener){
		instance = new HttpConnector(listener);
	}
	public static void sendHttpRequest(HttpRequest httpRequest) {
		MyLog.w(TAG, "httpFrame sendHttpRequest  -- ");
		if (httpRequest == null || !httpRequest.isComplete()) {
			if(httpRequest!=null){
				try {
					HttpThread.postHttpFinish(httpRequest, 
							httpRequest.createErrorResponse(HttpResponse.STATE_CREATE_REQUEST_ERROR, httpRequest));
				} catch (HttpOperateException e) {
					e.printStackTrace();
					throw new RuntimeException("自定义异常");
				}
			}
			return;
		}
		
		if(instance == null){
			instance = new HttpConnector(null);
		}
		
		instance.sendSynHttpRequest(httpRequest);

	}
	
	private void sendSynHttpRequest(HttpRequest httpRequest){
		if(httpRequest.getRequestType() == HttpRequest.REQUEST_TYPE_ACTION){
			synchronized (mHttpThreadAction) {
				if(instance.handleHttpRequest(httpRequest)){
					instance.requestThread(httpRequest.getRequestType());
				}
			}
		}
		else if(httpRequest.getRequestType() == HttpRequest.REQUEST_TYPE_DOWNLOAD){
			synchronized (mHttpThreadDown) {
				if(instance.handleHttpRequest(httpRequest)){
					instance.requestThread(httpRequest.getRequestType());
				}
			}
		}
		else if(httpRequest.getRequestType() == HttpRequest.REQUEST_TYPE_UPLOAD){
			synchronized (mHttpThreadUpload) {
				if(instance.handleHttpRequest(httpRequest)){
					instance.requestThread(httpRequest.getRequestType());
				}
			}
		}
		else{
		}
	}
	private boolean handleHttpRequest(HttpRequest httpRequest) {
		synchronized (object) {
			switch (httpRequest.getRequestType()) {
				case HttpRequest.FIRST_LEVEL_CLEAR_TOP:
					int size = mRequestQueue.size();
					for (int i=0;i<size;i++) {
						HttpRequest hr = mRequestQueue.get(i);
						if(hr.getRequestType() == httpRequest.getRequestType()){
							mRequestQueue.remove(hr);
							i--;
							size--;
						}
					}
					mRequestQueue.add(httpRequest);
					return true;
				case HttpRequest.FIRST_LEVEL_TOP:
					return addHttpRequest(false, httpRequest);
				case HttpRequest.FIRST_LEVEL_BOTTOM:
					return addHttpRequest(true, httpRequest);
				default:
					return addHttpRequest(true, httpRequest);
			}
		}
	}
	
	private boolean addHttpRequest(boolean isBottom,HttpRequest httpRequest){
		List<HttpRequest> sameRequestList = getAllSameRequestList(httpRequest);
		
		if(isRepeatRequest(sameRequestList, httpRequest)){
			MyLog.w(TAG, "httpFrame isRepeatRequest  ----------  "+httpRequest.getClass().getSimpleName());
			return false;
		}
		
		if (sameRequestList==null||sameRequestList.size()<=0) {
			if(isBottom){
				mRequestQueue.add(httpRequest);
			}else{
				mRequestQueue.add(0, httpRequest);
			}
			return true;
		} else {
			MyLog.w(TAG, "httpFrame --");
			for(int i=0;i<sameRequestList.size();i++){
				sameRequestList.get(i).addSameRequest(httpRequest);
			}
			if(sameRequestList.size()>1){
				MyLog.e(TAG, "httpFrame >>>>>>>>>>>>>>>>>>>>>>>>>>");
			}
			return false;
		}
		
	}
	private boolean isRepeatRequest(List<HttpRequest> sameRequestList, HttpRequest httpRequest){
		if(sameRequestList==null){
			return false;
		}
		for(int i=0;i<sameRequestList.size();i++){
			HttpRequest requestItem = sameRequestList.get(i);
			if(requestItem !=null){
				if(requestItem.isRepeatRequest(httpRequest)){
					return true;
				}
			}else{
				MyLog.e(TAG, "httpFrame isRepeatRequest <<<<<<<<<<<<<<<<<");
			}
		}
		return false;
	}
	
	
	private List<HttpRequest> getSameRequestListFromList(HttpRequest httpRequest, Vector<HttpRequest> requestQueue){
		List<HttpRequest> sameRequestList = null;
		for(int i=0;i<requestQueue.size();i++){
			HttpRequest requestItem = requestQueue.get(i);
			if(requestItem !=null){
				if(requestItem.equals(httpRequest)){
					if(sameRequestList == null){
						sameRequestList = new ArrayList<HttpRequest>();
					}
					sameRequestList.add(requestItem);
				}
			}else{
				MyLog.e(TAG, "httpFrame getSameRequestListFromList<<<<<<<<<<<<<<<<<<<<<<<<<<");
			}
			
		}
		
		return sameRequestList;
		
	}
	
	private List<HttpRequest> getAllSameRequestList(HttpRequest httpRequest){
		List<HttpRequest> sameWaitRequestList = getSameRequestListFromList(httpRequest, mRequestQueue);
		List<HttpRequest> sameDoingRequestList = getSameRequestListFromList(httpRequest, mRequestQueueCurr);
		List<HttpRequest> sameRequstList = new ArrayList<HttpRequest>();
		if(sameWaitRequestList!=null&&sameWaitRequestList.size()>0){
			sameRequstList.addAll(sameWaitRequestList);
			
		}
		if(sameDoingRequestList!=null&&sameDoingRequestList.size()>0){
			sameRequstList.addAll(sameDoingRequestList);
		}
		if(sameRequstList.size()>1){
		}
		
		return sameRequstList;
	}
	private void requestThread(int requestType) {
		if (requestType == HttpRequest.REQUEST_TYPE_ACTION) {

			int tsize = mThreadList.size();
			int tAlivesize = 0;
			for (int i=0;i<tsize;i++) {
				HttpThread ht = mThreadList.get(i);
				
				if (ht.getHttpThreadListener() == mHttpThreadAction) {
					
					if(ht.getState() == State.WAITING){
						synchronized (mHttpThreadAction) {
							mHttpThreadAction.notify();
						}
						MyLog.i(TAG, "httpFrame Thread : " +ht.getName() + ".......");
						return;
					}
					
					tAlivesize++;
					
				}
			}
			
			if (tAlivesize < MAX_THREAD_ACTION) {
				HttpThread ht = new HttpThread(mHttpThreadAction);
				ht.start();
				mThreadList.add(ht);
			}

		} else if (requestType == HttpRequest.REQUEST_TYPE_DOWNLOAD) {

			int tsize = mThreadList.size();
			int tAlivesize = 0;
			for (int i=0;i<tsize;i++) {
				HttpThread ht = mThreadList.get(i);
				
				if (ht.getHttpThreadListener() == mHttpThreadDown) {
					
					if(ht.getState() == State.WAITING){
						synchronized (mHttpThreadDown) {
							mHttpThreadDown.notify();
						}
						
						MyLog.i(TAG, "httpFrame Thread : " +ht.getName() + " ,,,,,,,,,,...");
						
						return;
					}
					tAlivesize++;
				}
			}
			
			if (tAlivesize < MAX_THREAD_DOWN) {
				HttpThread ht = new HttpThread(mHttpThreadDown);
				ht.start();
				
				mThreadList.add(ht);
			}

		} else if (requestType == HttpRequest.REQUEST_TYPE_UPLOAD) {
			int tsize = mThreadList.size();
			int tAlivesize = 0;
			for (int i=0;i<tsize;i++) {
				HttpThread ht = mThreadList.get(i);
				
				if (ht.getHttpThreadListener() == mHttpThreadUpload) {
					
					if(ht.getState() == State.WAITING){
						synchronized (mHttpThreadUpload) {
							mHttpThreadUpload.notify();
						}
						
						MyLog.i(TAG, "httpFrame Thread : " +ht.getName() + " ......");
						
						return;
					}
					tAlivesize++;
				}
			}
			
			if (tAlivesize < MAX_THREAD_UPLOAD) {
				HttpThread ht = new HttpThread(mHttpThreadUpload);
				ht.start();
				
				mThreadList.add(ht);
			}

		}
		
	}
	
	public static void clearRequest() {
		clearRequest(0);
	}
	
	public static void clearRequest(int requestType) {
		if(instance == null){
			return;
		}
		
		if(requestType == 0){
			instance.mRequestQueue.removeAllElements();
			return;
		}
		
		int size = instance.mRequestQueue.size();
		for (int i=0;i<size;i++) {
			HttpRequest hr = instance.mRequestQueue.get(i);
			if(hr.getRequestType() == requestType){
				instance.mRequestQueue.remove(hr);
				i--;
				size--;
			}
		}
	}

	private HttpThreadListener mHttpThreadAction = new HttpThreadListener() {

		@Override
		public HttpRequest getHttpRequest() {

			synchronized (object) {

				if (mRequestQueue.size() > 0) {
					for (HttpRequest hr : mRequestQueue) {
						if (hr.getRequestType() == HttpRequest.REQUEST_TYPE_ACTION) {
							mRequestQueue.remove(hr);
							mRequestQueueCurr.add(hr);
							return hr;
						}
					}
				}
			}

			return null;
		}

		@Override
		public void finishHttpRequest(HttpRequest httpRequest) {
			synchronized (object) {
				MyLog.w(TAG, "httpFrame finishHttpRequest ,,,,,,,,,,,,,"+mRequestQueueCurr.size());
				mRequestQueueCurr.remove(httpRequest);
			}
		}

		@Override
		public void requestWait(HttpThread httpThread) {
			synchronized (mHttpThreadAction) {
				try {
					MyLog.i(TAG, "httpFrame Thread : " +httpThread.getName() + " .............");
					mHttpThreadAction.wait();

				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			
		}

	};
	private HttpThreadListener mHttpThreadDown = new HttpThreadListener() {

		@Override
		public HttpRequest getHttpRequest() {

			synchronized (object) {

				if (mRequestQueue.size() > 0) {
					for (HttpRequest hr : mRequestQueue) {
						if (hr.getRequestType() == HttpRequest.REQUEST_TYPE_DOWNLOAD) {
							mRequestQueue.remove(hr);
							mRequestQueueCurr.add(hr);
							return hr;
						}
					}
				}
			}

			return null;
		}

		@Override
		public void finishHttpRequest(HttpRequest httpRequest) {
			synchronized (object) {
				mRequestQueueCurr.remove(httpRequest);
			}
		}

		@Override
		public void requestWait(HttpThread httpThread) {
			synchronized (mHttpThreadDown) {
				try {
					MyLog.i(TAG, "httpFrame Thread : " +httpThread.getName() + " ..........");
					mHttpThreadDown.wait();

				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	};
	private HttpThreadListener mHttpThreadUpload = new HttpThreadListener() {

		@Override
		public HttpRequest getHttpRequest() {

			synchronized (object) {

				if (mRequestQueue.size() > 0) {
					for (HttpRequest hr : mRequestQueue) {
						if (hr.getRequestType() == HttpRequest.REQUEST_TYPE_UPLOAD) {
							mRequestQueue.remove(hr);
							mRequestQueueCurr.add(hr);
							return hr;
						}
					}
				}
			}

			return null;
		}

		@Override
		public void finishHttpRequest(HttpRequest httpRequest) {
			synchronized (object) {
				mRequestQueueCurr.remove(httpRequest);
			}
		}

		@Override
		public void requestWait(HttpThread httpThread) {
			synchronized (mHttpThreadUpload) {
				try {
					MyLog.i(TAG, "httpFrame Thread : " +httpThread.getName() + ".......");
					mHttpThreadUpload.wait();

				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	};

}
